package com.lz.library.extension

import android.text.Editable
import android.text.TextWatcher
import android.view.View
import android.widget.TextView
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.*

/**
 * author: you : 2021/5/5
 *
 */

fun <T> Flow<T>.throttleFirst(duration: Long = 500L): Flow<T>  = flow {
    var lastTime = 0L
    collect {
        val currentTime = System.currentTimeMillis()
        if ((currentTime - lastTime) >= duration) {
            lastTime = currentTime
            emit(it)
        }
    }
}

@OptIn(ExperimentalCoroutinesApi::class, FlowPreview::class)
fun TextView.textChanged(duration: Long = 300): Flow<String> = callbackFlow {
    val textWatcher = object : TextWatcher {

        override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) = Unit

        override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) = Unit

        override fun afterTextChanged(s: Editable) {
            trySend(s.toString().trim())
        }
    }
    addTextChangedListener(textWatcher)
    awaitClose { removeTextChangedListener(textWatcher) }
}.debounce(duration)

@OptIn(ExperimentalCoroutinesApi::class)
fun Array<out View>.click(duration: Long = 500L): Flow<View> = callbackFlow<View> {
    val clickListener = View.OnClickListener { trySend(it) }
    this@click.forEach { it.setOnClickListener(clickListener) }
    awaitClose { this@click.forEach { it.setOnClickListener(null) } }
}.throttleFirst(duration)

@OptIn(ExperimentalCoroutinesApi::class)
fun View.click(duration: Long = 500L): Flow<View> = callbackFlow {
    setOnClickListener { trySend(it) }
    awaitClose { setOnClickListener(null) }
}.throttleFirst(duration)

fun countDown(count: Int): Flow<Int> = flow {
    for (i in count downTo 0) {
        emit(i)
        if (i != 0) delay(1000)
    }
}

fun timer(interval: Long): Flow<Long> = flow {
    var i: Long = 0
    while (true) {
        emit(i++)
        delay(interval)
    }
}